<template>
  <van-cell-group :border="border">
    <dynamic-form-item
      v-for="field in formDef.fields"
      ref="formItem"
      v-model="formData[field.name]"
      :key="field.name"
      :field="field"
      :data ="formData"

      :rights="rights[field.name]"
      :params ="params"

      @cinput="handleInput($event)"
    />
  </van-cell-group>
</template>

<script>
import FormOptions from './constants/formoptions'
import FormUtil from './utils/formUtil'

export default {
  props: {
    formDef: {
      type: Object,
      required: true
    },
    value: {
      type: Object
    },
    readonly: {
      type: Boolean,
      default: false
    },
    permissions: {
      type: Object
    },
    columnMinWidth: {
      type: String
    },
    validateImmediately: {// 是否初始验证
      type: Boolean,
      default: true
    },
    // 流程参数
    defId: String,
    taskId: String,
    bpmnInstId: String,
    hasScript: Boolean
  },
  data() {
    return {
      rights: {},
      responseFormula: {},
      responseLinkages: {},
      responseVerifys: [], // 表单提交校验
      border: false,
      isInitialization: false
    }
  },
  computed: {
    formData() {
      return this.value
    },
    params() { // 扩展参数
      return {
        code: this.formDef.code,
        responseFormula: this.responseFormula,
        responseLinkages: this.responseLinkages,
        readonly: this.readonly,
        permissions: this.rights,
        defId: this.defId,
        taskId: this.taskId,
        bpmnInstId: this.bpmnInstId
      }
    }
  },
  watch: {
    formDef() {
      this.border = true
      this.initResponseFields()
    },
    value() {
      // 延迟验证
      this.$nextTick(() => {
        this.getFormValidator()
      })
    }
  },
  mounted() {
    if (this.validateImmediately) { this.getFormValidator() }
    // 初始化脚本

    if (this.isInitialization && this.hasScript) {
      this.$emit('load-script')
    }
  },
  created() {
    this.initResponseFields()

    if (!this.isInitialization) {
      this.initJForm()
      this.isInitialization = true
    }
  },
  methods: {
    getLabelWidth() {
      if (this.formDef.attrs.labelWidth !== null && this.formDef.attrs.labelWidthUnit !== '') {
        return this.formDef.attrs.labelWidth + this.formDef.attrs.labelWidthUnit
      }
    },
    /**
     * 初始化字段
     */
    initResponseFields() {
      const fields = this.formDef.fields
      if (!fields) { return }
      const data = { ...this.value }

      const permissions = { ...this.permissions }

      fields.forEach(item => {
        item.code = this.formDef.code
        // 设置默认值
        this.setExistingValue(data, item)
        // 设置权限
        this.rights[item.name] = this.getPermissions(permissions, item) || this.getDefaultRigths(item)
        // 初始化需要进行公式计算的字段
        this.initResponseFormula(item)
        // 初始化需要进行联动数据的字段
        this.initResponseLinkages(item)
      })
      // 初始化运行公式计算
      this.initRunCalFormula()
      // 设置默认值
      this.setDefaultValue()
    },
    // 设置值
    setDefaultValue() {
      this.handleInput({ ...this.formData })
    },
    handleInput(data) {
      // 这里没有上报event，直接就是value了
      this.$emit('input', data)
    },
    // 设置已经存在的值
    setExistingValue(data, item) {
      const { name } = item
      if (data[name] !== undefined) { return }
      this.formData[name] = data[name] || FormUtil.getFieldDefaultValue(item, (n, d) => {
        this.formData[n] = d
        // 延迟验证
        this.$nextTick(() => {
          this.getFormValidator()
        })
      })
    },

    // 获取权限
    getPermissions(permissions, { name, field_type }) {
      if (this.$utils.isEmpty(permissions)) { return }
      const fieldType = field_type
      let rightsValue = null
      const isNonInputField = FormOptions.t.NON_INPUT_FIELD_TYPES.findIndex((n) => { return n === fieldType }) > -1
      let isSpecial = false
      if (isNonInputField && permissions.fields) { // 非输入字段
        rightsValue = permissions.fields[name] ? permissions.fields[name] : null
      } else if (fieldType === 'approval_opinion' && permissions.opinions) { // 意见 特殊处理
        rightsValue = permissions.opinions[name] ? permissions.opinions[name] : null
      } else if (fieldType === 'table' && permissions.tables) { // 子表
        isSpecial = true
        rightsValue = permissions.tables[name] ? permissions.tables[name] : null
      } else { // 字段
        rightsValue = permissions.fields[name] ? permissions.fields[name] : null
      }
      if (this.readonly && !isNonInputField && !isSpecial) { // 只读权限
        rightsValue = rightsValue !== FormOptions.t.PERMISSIONS.HIDE ? FormOptions.t.PERMISSIONS.READ : rightsValue
      }

      return rightsValue
    },
    /**
     * 默认权限
     */
    getDefaultRigths(item) {
      var hideRights = item.field_options.hide_rights
      if (this.$utils.isNotEmpty(hideRights) && hideRights) {
        return FormOptions.t.PERMISSIONS.HIDE
      }
      var readRights = item.field_options.read_rights
      if (this.$utils.isNotEmpty(readRights) && readRights) {
        return FormOptions.t.PERMISSIONS.READ
      }
      return
    },

    // 初始化需要进行公式计算的字段
    initResponseFormula(item) {
      FormUtil.setResponseFormula(this.responseFormula, item)
    },
    // 初始化运行公式计算
    initRunCalFormula() {
      // 不需要字段的进行公式计算 比如获取但其当前时间
      FormUtil.runCalFormula(this.responseFormula[FormUtil.NOT_NEED_FIELD], this.formData || {}, this.formDef.code)
      const fields = this.formDef.fields
      fields.forEach(field => {
        const key = field.code + '.' + field.name
        const formula = this.params.responseFormula[key]
        if (formula) {
          FormUtil.runCalFormula(formula, this.formData, field)
        }
      })
    },
    initResponseLinkages(item) {
      FormUtil.setResponseLinkages(this.responseLinkages, item)
    },
    getFormSubmitVerify() {
      const verifys = this.formDef.attrs ? this.formDef.attrs.verifys : []
      let errors = {}
      if (this.$utils.isEmpty(verifys)) { return errors }
      verifys.forEach((verify) => {
        if (!FormUtil.runFormSubmitVerify(verify.formula, this.formData, this.formDef.code)) {
          errors = {
            result: false,
            msg: verify.msg
          }
          return false
        }
      })
      return errors
    },
    /**
     * 初始化脚本
     */
    initJForm() {
      var id = 'JForm'
      var script = document.getElementById(id)
      if (script) {
        script.parentNode.removeChild(script)
      }
      if (this.formDef.attrs && this.formDef.attrs.mobile_script) {
        var code = this.formDef.attrs.mobile_script
        script = document.createElement('script')
        script.type = 'text/javascript'
        script.id = id
        document.body.appendChild(script)
        try {
          script.appendChild(document.createTextNode(code))
        } catch (ex) {
          script.text = code
        }
        document.body.appendChild(script)
      }
    },
    /**
     * 表单验证
     */
    getFormValidator() {
      if (!this.$refs.formItem) { return }
      const $validate = []
      this.$refs.formItem.forEach(el => {
        if (el.field.field_type === 'table') {
          const tableEls = el.getEl()
          if (!tableEls) return true
          tableEls.forEach(tableEl => {
            const v = new Promise((resolve, reject) => {
              tableEl.getFormValidator().validate().then((result) => {
                resolve(result)
              })
            })
            $validate.push(v)
          })
        } else {
          const v = new Promise((resolve, reject) => {
            el.getFormValidator().validate().then((result) => {
              resolve(result)
            })
          })

          $validate.push(v)
        }
      })

      return Promise.all($validate)
    },
    /**
     * 表单验证
     */
    getFormErrors() {
      if (!this.$refs.formItem) { return }
      let $errors = []
      this.$refs.formItem.forEach(el => {
        if (el.field.field_type === 'table') {
          const tableEls = el.getEl()
          if (!tableEls) return true
          tableEls.forEach(tableEl => {
            const errorItems = tableEl.getFormErrors().items
            $errors = [...$errors, ...errorItems]
          })
        } else {
          const errorItems = el.getFormErrors().items
          $errors = [...errorItems]
        }
      })

      return $errors
    }

  }
}
</script>

<style lang="scss">
.dynamic-form {
  padding: 10px;
  .el-input{
    width: 100%;
  }
  .el-select{
        width: 100%;
  }
  .page-header {
      border: 1px solid transparent;
      background-color: #dff0fe;
      margin-bottom: 5px;
      .title {
        font-size: 15px;
        font-weight: bold;
        color: #222;
        text-align: left;
        padding: 8px 10px 10px;
        margin: 0;
      }
      .desc {
        word-wrap: break-word;
        word-break: normal;
        text-indent: 0;
        line-height: 1.6;
        margin: 0 0 11px;
        padding: 3px 30px 8px;
      }
  }

}
</style>
